} break; case 'meta_data': if ( is_array( $value ) ) { foreach ( $value as $meta ) { $order->update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' ); } } break; default: if ( is_callable( array( $order, "set_{$key}" ) ) ) { $order->{"set_{$key}"}( $value ); } break; } } } /** * Filters an object before it is inserted via the REST API. * * The dynamic portion of the hook name, `$this->post_type`, * refers to the object type slug. * * @param WC_Data $order Object object. * @param WP_REST_Request $request Request object. * @param bool $creating If is creating a new object. */ return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}_object", $order, $request, $creating ); } /** * Save an object data. * * @since 3.0.0 * @throws WC_REST_Exception But all errors are validated before returning any data. * @param WP_REST_Request $request Full details about the request. * @param bool $creating If is creating a new object. * @return WC_Data|WP_Error */ protected function save_object( $request, $creating = false ) { try { $object = $this->prepare_object_for_database( $request, $creating ); if ( is_wp_error( $object ) ) { return $object; } // Make sure gateways are loaded so hooks from gateways fire on save/create. WC()->payment_gateways(); if ( ! is_null( $request['customer_id'] ) && 0 !== $request['customer_id'] ) { // Make sure customer exists. if ( false === get_user_by( 'id', $request['customer_id'] ) ) { throw new WC_REST_Exception( 'woocommerce_rest_invalid_customer_id', __( 'Customer ID is invalid.', 'woocommerce' ), 400 ); } // Make sure customer is part of blog. if ( is_multisite() && ! is_user_member_of_blog( $request['customer_id'] ) ) { add_user_to_blog( get_current_blog_id(), $request['customer_id'], 'customer' ); } } if ( $creating ) { $object->set_created_via( 'rest-api' ); $object->set_prices_include_tax( 'yes' === get_option( 'woocommerce_prices_include_tax' ) ); $object->calculate_totals(); } else { // If items have changed, recalculate order totals. if ( isset( $request['billing'] ) || isset( $request['shipping'] ) || isset( $request['line_items'] ) || isset( $request['shipping_lines'] ) || isset( $request['fee_lines'] ) || isset( $request['coupon_lines'] ) ) { $object->calculate_totals( true ); } } // Set coupons. $this->calculate_coupons( $request, $object ); // Set status. if ( ! empty( $request['status'] ) ) { $object->set_status( $request['status'] ); } $object->save(); // Actions for after the order is saved. if ( true === $request['set_paid'] ) { if ( $creating || $object->needs_payment() ) { $object->payment_complete( $request['transaction_id'] ); } } return $this->get_object( $object->get_id() ); } catch ( WC_Data_Exception $e ) { return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() ); } catch ( WC_REST_Exception $e ) { return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); } } /** * Prepare objects query. * * @since 3.0.0 * @param WP_REST_Request $request Full details about the request. * @return array */ protected function prepare_objects_query( $request ) { // This is needed to get around an array to string notice in WC_REST_Orders_V2_Controller::prepare_objects_query. $statuses = $request['status']; unset( $request['status'] ); $args = parent::prepare_objects_query( $request ); $args['post_status'] = array(); foreach ( $statuses as $status ) { if ( in_array( $status, $this->get_order_statuses(), true ) ) { $args['post_status'][] = 'wc-' . $status; } elseif ( 'any' === $status ) { // Set status to "any" and short-circuit out. $args['post_status'] = 'any'; break; } else { $args['post_status'][] = $status; } } // Put the statuses back for further processing (next/prev links, etc). $request['status'] = $statuses; return $args; } /** * Get the Order's schema, conforming to JSON Schema. * * @return array */ public function get_item_schema() { $schema = parent::get_item_schema(); $schema['properties']['coupon_lines']['items']['properties']['discount']['readonly'] = true; return $schema; } /** * Get the query params for collections. * * @return array */ public function get_collection_params() { $params = parent::get_collection_params(); $params['status'] = array( 'default' => 'any', 'description' => __( 'Limit result set to orders which have specific statuses.', 'woocommerce' ), 'type' => 'array', 'items' => array( 'type' => 'string', 'enum' => array_merge( array( 'any', 'trash' ), $this->get_order_statuses() ), ), 'validate_callback' => 'rest_validate_request_arg', ); return $params; } }